package com.pixelengine;
//created 2022-2-13 1200 by wf
import com.google.gson.Gson;
import com.pixelengine.DataModel.*;
import com.pixelengine.tools.JScriptTools;
import com.pixelengine.JTileRangeTool;
import com.pixelengine.tools.JTileResolutionTool;
import org.apache.hadoop.hbase.util.Bytes;
import org.gdal.gdal.Dataset ;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;

import java.io.File;

public class WOrderWorker {



    public WExportResult processOneOrder(WConfig config, JExportOrder order ){
        WExportResult r = new WExportResult() ;
        r.state = 9 ;

        try{
            ///////////////////////////////////////////////////////////////////
            //
            //通过geojson计算四角范围
            System.out.println("compute geojson extent ");
            String geojsonFile = config.pedir + order.geojsonRelFilepath ;
            JGeojsonUtils.WExtent extent = JGeojsonUtils.extent(geojsonFile );
            if( extent==null ){
                throw new Exception("failed to compute geojson extent.") ;
            }
            System.out.println("geojson extent l,r t,b:"+extent.left+","+extent.right+" "+extent.top+","+extent.bottom);

            ///////////////////////////////////////////////////////////////////
            //
            //init pe
            HBasePeHelperCppConnector cc = new HBasePeHelperCppConnector();


            ///////////////////////////////////////////////////////////////////
            //
            //read script text
            String scriptFilePath = config.pedir + order.scriptRelFilepath ;
            System.out.println("read script text "+scriptFilePath) ;
            String scriptText = WTextFile.readFileAsString(scriptFilePath) ;
            if(scriptText==null) {
                throw new Exception("read scriptText failed");
            }

            ///////////////////////////////////////////////////////////////////
            //
            //计算数据集zlevel
            System.out.println("get dsname array for compute zlevel");
            String dsNameArrJsonText = cc.GetDatasetNameArray("com/pixelengine/HBasePixelEngineHelper",
                    scriptText) ;
            if( dsNameArrJsonText==null ){
                throw new Exception("HBasePeHelperCppConnector.GetDatasetNameArray failed") ;
            }
            Gson gson = new Gson();
            JDsNameArrayResult dsnamesResult = gson.fromJson(dsNameArrJsonText , JDsNameArrayResult.class) ;
            if( dsnamesResult.status != 0 ){
                throw new Exception("bad JDsNameArrayResult, " + dsnamesResult.error) ;
            }
            if( dsnamesResult.data.length == 0 ){
                throw new Exception("None valid dsname in script");
            }
            JRDBHelperForWebservice rdb = new JRDBHelperForWebservice() ;
            int maxZoom = -1 ;
            //int maxDataByteLen = 0 ;
            for(int ids = 0 ; ids < dsnamesResult.data.length ; ++ ids ){
                JProduct pdt =rdb.rdbGetProductInfoByName( dsnamesResult.data[ids] ) ;
                if( pdt==null ){
                    throw new Exception("Undefined Product of "+dsnamesResult.data[ids] );
                }
                maxZoom = Math.max( maxZoom , pdt.maxZoom) ;
                //maxDataByteLen = Math.max(maxDataByteLen,pdt.getDataByteLen()) ;
            }
            if( maxZoom<0 ){
                throw new Exception("Invalid maxZoom "+maxZoom);
            }
            System.out.println("maxZoom:"+maxZoom) ;
            //set maxZoom 15 , about 4.29m , xtilenum:32768
            if( maxZoom>15 ){
                maxZoom = 15 ;
                System.out.println("adjust maxZoom to :"+maxZoom) ;
            }

            ///////////////////////////////////////////////////////////////////
            //
            //计算瓦片x，y范围
            final int tileSize = 256 ;
            final int maxTileNum1D = 50 ;//50x50 in tiles, 12800x12800 in pixels.
            System.out.println("compute tile range");
            JTileRangeTool.TileXYRange tileRange = JTileRangeTool.computeTileRangeByLonglatExtent(
                    extent.left,
                    extent.right,
                    extent.top,
                    extent.bottom,
                    maxZoom,
                    tileSize) ;
            if( tileRange==null ){
                throw new Exception("failed to compute tileRange");
            }
            System.out.println("tile range xmin,xmax ymin,ymax:"
                + tileRange.xmin + "," + tileRange.xmax + " "
                    + tileRange.ymin+","+tileRange.ymax
            );


            //计算0号瓦片，获得结果数据类型与波段数目,如果计算0号瓦片失败，也是报异常不再进行后面计算了
            System.out.println("compute zero tile (0,0,0)");
            String extraText = "{\"datetime\":"+order.datetime+"}" ;
            String scriptWithSDUI = JScriptTools.assembleScriptWithSDUI( scriptText , order.sdui ) ;
            TileComputeResult zeroTileResult = cc.RunScriptForTileWithoutRenderWithExtra(
                    "com/pixelengine/HBasePixelEngineHelper",
                    scriptWithSDUI,
                    extraText,
                    0,0,0
            ) ;
            if(zeroTileResult==null ){
                throw new Exception("zeroTileResult is null") ;
            }
            if( zeroTileResult.status!=0 ){
                throw new Exception("compute zeroTileResult failed") ;
            }
            System.out.println("zeroTileResult ok, dataType:"+zeroTileResult.outType+", nband:"+zeroTileResult.nbands);


            ///////////////////////////////////////////////////////////////////
            //
            //根据最大限量从新计算x，y范围，从config.json中读取
            int tileXNum = tileRange.xmax - tileRange.xmin + 1 ;
            int tileYNum = tileRange.ymax - tileRange.ymin + 1 ;
            JExportPart[] exportParts = JExportPart.computeParts(tileRange,maxTileNum1D) ;

            if( exportParts.length>1 ){
                System.out.println("Request "+tileXNum+" x "+tileYNum
                + " is exceeded max tile number of one part("
                + maxTileNum1D+" x "+maxTileNum1D+") ");
                System.out.println("Output will be "+exportParts.length+" parts.");
            }
            else{
                System.out.println("Output one part.");
            }


            ///////////////////////////////////////////////////////////////////
            //
            //计算分辨率
            double theReso = JTileResolutionTool.computeResolution(maxZoom , tileSize);
            System.out.println("the resolution:"+theReso);


            ///////////////////////////////////////////////////////////////////
            //
            //在存储中打开结果文件
            String allPartNumTag = String.format("%03d",exportParts.length) ;
            String clipVectorFilename = config.pedir + order.geojsonRelFilepath;
            String[] outTifRefFilenames = new String[exportParts.length] ;
            for(int ipart = 0 ; ipart < exportParts.length; ++ ipart ) {
                String outTiffRelFilepath = "" ;
                if( exportParts.length==1 ) {
                    outTiffRelFilepath=order.resultRelFilepath.replace(".json",".tif") ;
                }else{
                    String partTag = String.format("%03d",ipart+1) ;
                    outTiffRelFilepath=order.resultRelFilepath.replace(".json",
                            "_" + partTag + "_of_" + allPartNumTag + ".tif") ;
                }
                outTifRefFilenames[ipart] = outTiffRelFilepath ;
                System.out.println("begin for "+outTiffRelFilepath);
                JExportPart part1 = exportParts[ipart] ;
                double[] geoTrans = new double[6] ;
                geoTrans[0] = tileRange.left + (part1.startTileXInclude-tileRange.xmin)*256.0*theReso ;
                geoTrans[1] =  theReso;
                geoTrans[2] = 0 ;
                geoTrans[3] = tileRange.top - (part1.startTileYInclude-tileRange.ymin)*256.0*theReso;
                geoTrans[4] = 0 ;
                geoTrans[5] = -theReso ;
                WExportProcesser exporter = new WExportProcesser() ;
                boolean isok = exporter.exportPart(
                        part1,
                        tileSize,
                        zeroTileResult.nbands,
                        order.fillvalue,
                        geoTrans,
                        zeroTileResult.dataType,
                        cc,
                        scriptWithSDUI,
                        extraText,
                        maxZoom,
                        config.pedir,
                        outTiffRelFilepath,
                        config.gdalwarp,
                        clipVectorFilename
                );
                if(isok==false) {
                    System.out.println("failed to process part "+ipart);
                }
            }

            //结束返回
            System.out.println("order process done.");
            r.data = outTifRefFilenames[0] ;//保存tif相对路径
            r.dataArray = outTifRefFilenames ;
            r.state = 0 ;//everything ok.
            return r;
        }catch (Exception ex )
        {
            r.state = 99 ;//everything ok.
            r.message = "WOrderWorker.processOneOrder exception:"+ex.getMessage() ;
            return r;
        }
    }
}
